from selenium import webdriver
from scrapy.http import HtmlResponse
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.proxy import Proxy
from selenium.webdriver.common.proxy import ProxyType
from selenium.webdriver.common.keys import Keys
import time

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import random
from selenium.common.exceptions import TimeoutException

from twisted.internet import defer
from twisted.internet.error import TimeoutError, DNSLookupError, \
        ConnectionRefusedError, ConnectionDone, ConnectError, \
        ConnectionLost, TCPTimedOutError
from twisted.internet import defer, threads
from twisted.python.failure import Failure
import threading

import traceback

class DriveManage(object):
    iCount = 0
    m_mutex = threading.Lock()

    def CreateChorme(self, request):
        option = Options()
        prefs = {"profile.managed_default_content_settings.images": 2}
        option.add_experimental_option("prefs", prefs)
        desired_capabilities = DesiredCapabilities.CHROME  # 修改页面加载策略
        #  desired_capabilities["pageLoadStrategy"] = "none"  # 注释这两行会导致最后输出结果的延迟，即等待页面加载完成再输出
        option.add_argument("--disable-gpu");
        option.add_argument("--no-sandbox");
        option.add_argument("--allow-insecure-localhost");
        option.add_argument('--headless')
        if "User-Agent" in request.headers:
            a = request.headers["User-Agent"]
            strHeaders = "user-agent=" + a.decode()
            option.add_argument(strHeaders)
        desired_capabilities = option.to_capabilities()
        if "proxy" in request.meta:
            desired_capabilities['proxy'] = {
                "httpProxy": request.meta["proxy"],
                "ftpProxy": None,
                "sslProxy": None,
                "noProxy": None,
                "proxyType": "MANUAL",
                "class": "org.openqa.selenium.Proxy",
                "autodetect": False
            }

        driver = webdriver.Chrome(executable_path=".\\tool\\chromedriver.exe", chrome_options=option,
                                  desired_capabilities=desired_capabilities)

        driver.set_script_timeout(15)  # 这两种设置都进行才有
        driver.set_page_load_timeout(15)
        driver.implicitly_wait(15)
        return driver

    def OpenChorme(self, request):
        while True:
            self.m_mutex.acquire()
            iCount = self.iCount
            self.m_mutex.release()
            if iCount <8:
                self.m_mutex.acquire()
                self.iCount = self.iCount + 1
                self.m_mutex.release()
                driver = self.CreateChorme(request)
                break
            else:
                time.sleep(1)
        return driver

    def CloseDrive(self, driver):
        driver.quit()
        self.m_mutex.acquire()
        self.iCount = self.iCount - 1
        self.m_mutex.release()

    def Openfirfox(self, request):
        # 创建的新实例驱动
        options = webdriver.FirefoxOptions()
        # 火狐无头模式
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')

        driver = webdriver.Firefox(executable_path=".\\tool\\geckodriver.exe")
        driver.set_script_timeout(15)  # 这两种设置都进行才有
        driver.set_page_load_timeout(15)
        driver.implicitly_wait(8)
        return driver

    _instance = None

    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(DriveManage, cls).__new__(cls, *args, **kw)
        return cls._instance


class dynamicMiddleware(object):

    iCount = 0
    iCountExcept = 0
    m_mutexCount = threading.Lock()
    def plusCount(self):
        self.m_mutexCount.acquire()
        self.iCount=self.iCount+1
        self.m_mutexCount.release()

    def plusCountExcept(self):
        self.m_mutexCount.acquire()
        self.iCountExcept = self.iCountExcept + 1
        self.m_mutexCount.release()


    def process_request(self, request, spider):
        if not "Dynamic" in spider.type:
            return
        return threads.deferToThread(self.request_main, request, spider)
       # threads.addCallback()
  #  def handle_Callback(self):

  #  def error_Handle(self):

    def request_main(self, request, spider):
        try:
            driver = DriveManage().OpenChorme(request)
            driver.get(request.url)
            #cookie_list = driver.get_cookies()

            # driver.get(request.url)
            rendered_body = driver.page_source
            if "funcRequestHtmlData" in request.meta:
                f = getattr(spider, request.meta["funcRequestHtmlData"])
                rendered_body = f(driver)
            DriveManage().CloseDrive(driver)
            self.plusCount()
            return HtmlResponse(request.url, body=rendered_body, encoding="utf-8")
        except TimeoutException:
            DriveManage().CloseDrive(driver)
            self.plusCountExcept()
            raise ConnectionRefusedError()
        except Exception as e:
            print('e.message:\t%s' % str(e))
            print('traceback.print_exc():')
            traceback.print_exc()
            DriveManage().CloseDrive(driver)
            self.plusCountExcept()
            raise ConnectionRefusedError()

  #  def request_error(self, driver, ):
